#include "Level1.h"


#include "HUD.h"

//#include "GnashManager.h"
//#include "GnashUtils.h"

using namespace std;
using namespace Ogre;
//using namespace luabind;

//#define BIT(x) (1<<(x))
//enum collisiontypes {
//	COL_NOTHING = 0,
//	COL_ACTOR   = BIT(1),
//	COL_BIKE    = BIT(2),
//	COL_WALL    = BIT(3),
//	COL_POWERUP = BIT(4),
//	COL_LASER   = BIT(5)
//};


Level1 Level1::mLevel1;
Car* car;
//SceneNode* carLightNode;

std::vector<GenericCamera*> cameras;
GenericCamera* cam;
ChaseCamera* chaseCam;
FlyCamera* flyCam;
bool fixCamera = false;

HUD *hud;

SceneNode* sunNode;
Billboard* sunBB;
Light*     sunLight;

BtOgre::DebugDrawer *dbgdraw;
bool showDebug = false;

bool useShaders = true;
bool showWireframe = true;

enum Shapes { CONVEX, BOX, SPHERE, CYLINDER, TRIMESH };
static std::map<std::string, Shapes> shapeMap;


/**
 * \class MaterialSwitcher
 * \author gershon
 * \date 02/26/2010
 * \file MenuState.cpp
 * \brief
 */
class BaseMaterialSwitcher : public Ogre::MaterialManager::Listener
	{
	protected:
		Material* baseMat;
	public:
		BaseMaterialSwitcher() {
			baseMat = static_cast<Material*>(MaterialPtr(MaterialManager::getSingleton().getByName("base_material")).getPointer());
			baseMat->compile();
			baseMat->load();
		}

		Ogre::Technique *handleSchemeNotFound(unsigned short, const Ogre::String& schemeName, Ogre::Material* mat, unsigned short, const Ogre::Renderable*) {
			//if(mat->getNumSupportedTechniques()==0) return mat->getTechnique(0);

			if (mat->getName()!="base_material") return NULL;
			if (schemeName == "default")
				return baseMat->getTechnique(0);
			else
				if (schemeName == "NoShaders")
					return baseMat->getTechnique(1);

			return NULL;
		}
	};

class BaseRTTListener : public RenderTargetListener
	{
	public:
		BaseRTTListener(SceneManager* smgr, Viewport* vp, Ogre::MaterialManager::Listener *ml) :
				mSceneMgr(smgr),
				mViewport(vp),
				mMatListener(ml) {}
	protected:
		SceneManager					*mSceneMgr;
		Viewport        				*mViewport;
		Ogre::MaterialManager::Listener *mMatListener;

		void preRenderTargetUpdate(const RenderTargetEvent &evt) {
			MaterialManager::getSingleton().addListener( mMatListener );
		}

		void postRenderTargetUpdate(const RenderTargetEvent &evt) {
			MaterialManager::getSingleton().removeListener( mMatListener );
		}
	};

//extern ContactAddedCallback     gContactAddedCallback;
//static bool customContactCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
//{
//
////    SoundManager* soundMgr = OgreApplication::getSingletonPtr()->getSoundManager();
////    int thudIndex, thudChannel=0;
////    thudIndex = soundMgr->CreateStream(String("Thud-Adrian_K-2016.wav"));
////    soundMgr->PlaySound(thudIndex, NULL, &thudChannel);
//
//	return true;
//}


void Level1::enter()
{
//	L = OgreApplication::getSingleton().L;

	mCurrentObject = NULL;

	mRoot = Root::getSingletonPtr();

	mSceneMgr = mRoot->createSceneManager(ST_GENERIC);

//    mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
//    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);

//    mSceneMgr->setShadowTexturePixelFormat(Ogre::PF_FLOAT16_R);
//    mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
//    mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
	mSceneMgr->setShadowTextureSelfShadow(true);
	mSceneMgr->setShadowCasterRenderBackFaces(true);
	
	mSceneMgr->setShadowFarDistance(100);
//    mSceneMgr->setShadowTextureSize(2048);
	mSceneMgr->setShadowTextureSettings(1024,8,PF_FLOAT16_R);
//    mSceneMgr->setShadowTextureFadeStart(0.0f);
//    mSceneMgr->setShadowTextureFadeEnd(1.0f);

//    mSceneMgr->setShadowTextureCasterMaterial("ShadowCaster");
//    mSceneMgr->setShadowTextureReceiverMaterial("ShadowReceiver");

	mCamera = mSceneMgr->createCamera("Camera");
	mCamera->setNearClipDistance(0.1);
	mCamera->setFarClipDistance(10000);
	mCamera->setFOVy(Degree(53));
	mViewport = mRoot->getAutoCreatedWindow()->addViewport(mCamera);
	mViewport->setBackgroundColour(ColourValue::Black);

	OgreApplication::getSingletonPtr()->setCamera(mCamera);




	timeMulti = 1;
	initBullet();

	DotSceneLoader dsl;
	dsl.parseDotScene("scene.xml", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mSceneMgr);

//    SceneNode* skyDome = mSceneMgr->getSkyDomeNode();
//    skyDome->getAttachedObject(0)->setCastShadows(false);
//    skyDome->getAttachedObject(0)->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY);

	SceneNode* rootNode = mSceneMgr->getRootSceneNode();

	// Physicize scene...
	SceneNode::ChildNodeIterator iter = rootNode->getChildIterator();
	while (iter.hasMoreElements()) {
			SceneNode* node = static_cast<SceneNode*>(iter.getNext());
			if (node->numAttachedObjects()==0) continue;
			Entity* ent = static_cast<Entity*>(node->getAttachedObject(0));
			String nodeName = node->getName();

			if (dsl.getProperty(nodeName, "mass")=="" && dsl.getProperty(nodeName, "shape")=="") continue;

			Real mass = StringConverter::parseReal(dsl.getProperty(nodeName, "mass"));
			String shapeStr = dsl.getProperty(nodeName, "shape");

			BtOgre::StaticMeshToShapeConverter converter(ent);
			btCollisionShape *shape;

			shapeMap["box"] = BOX;
			shapeMap["sphere"] = SPHERE;
			shapeMap["cylinder"] = CYLINDER;
			shapeMap["trimesh"] = TRIMESH;

			switch (shapeMap[shapeStr]) {
				case BOX:
					shape = converter.createBox();
					break;
				case SPHERE:
					shape = converter.createSphere();
					break;
				case CYLINDER:
					shape = converter.createCylinder();
					break;
				case TRIMESH:
					shape = converter.createTrimesh();
					break;
				case CONVEX:
				default:
					shape = converter.createConvex();
				}

			BtOgre::RigidBodyState *state = new BtOgre::RigidBodyState(node);

			bool isStatic = (mass == 0);
			btVector3 inertia(0,0,0);

			if (!isStatic)
				shape->calculateLocalInertia(mass, inertia);

			btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, state, shape, inertia);
			btRigidBody* body = new btRigidBody(rigidBodyCI);
//        if(isStatic)
//            phyWorld->addRigidBody(body, COL_WALL, COL_ACTOR | COL_BIKE | COL_LASER);
//        else
//            phyWorld->addRigidBody(body, COL_ACTOR, COL_BIKE | COL_WALL | COL_LASER);
			phyWorld->addRigidBody(body);
		}


	sunNode = mSceneMgr->getSceneNode("Sun");
	Vector3 sunPos = sunNode->getPosition();

	sunLight = static_cast<Light*>(sunNode->getAttachedObject(0));
	
	LensFlare* lensflare = new LensFlare(sunPos, mCamera, mSceneMgr, sunPos.length());
	mRoot->addFrameListener(lensflare);

	BillboardSet* sunBBS = mSceneMgr->createBillboardSet("SunBillboard");
//    sunBB = sunBBS->createBillboard(Vector3::ZERO, sunLight->getDiffuseColour());
	sunBB = sunBBS->createBillboard(Vector3::ZERO, ColourValue(0.7,0.6,0.1,1.0));
	sunBB->setDimensions(sunPos.length()*1.5,sunPos.length()*1.5);
	sunBBS->setMaterialName("lensflare/source");
	sunNode->attachObject(sunBBS);


	/// Car
	car = new Car(mSceneMgr);
//	car->loadMesh(mSceneMgr, "SportsCar", "SportsCar.mesh");
//	car->init(mRoot, mSceneMgr, phyWorld, "SportsCar.xml");

//	car->loadMesh(mSceneMgr, "Mitsubishi300", "Mitsubishi300.mesh");
//	car->init(mRoot, mSceneMgr, phyWorld, "Mitsubishi300.xml");

	EnvMapGenerator* emg = new EnvMapGenerator(mRoot, mSceneMgr);
	emg->mNode = car->getSceneNode();
	car->addComponent("EnvMapGenerator", emg);

	car->loadMesh("Golf", "Golf.mesh");
	car->init(mRoot, mSceneMgr, phyWorld, "Golf.xml");

//	Ogre::Light* dl = mSceneMgr->createLight();
////	dl->setType(Light::LT_SPOTLIGHT);
//	dl->setType(Light::LT_DIRECTIONAL);
//	dl->setDirection(sunLight->getDirection());
//	dl->setPosition(dl->getDirection()*-10.f);
//	dl->setCastShadows(true);
////	dl->setShadowFarDistance(20.f);
////	dl->setShadowNearClipDistance(0.f);
////	dl->setAttenuation(40,1,1,0);
////	dl->setDiffuseColour(1,0,0);
//	dl->setDiffuseColour(sunLight->getDiffuseColour());
////	carLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("carLightNode");
////	carLightNode->attachObject(dl);


	chaseCam = new ChaseCamera(mSceneMgr);
	mRoot->addFrameListener(chaseCam);

	flyCam = new FlyCamera(mSceneMgr);
	mRoot->addFrameListener(flyCam);

	cameras.push_back(chaseCam);
	cameras.push_back(flyCam);
	cam = chaseCam;

	// attach to chase camera
	chaseCam->attachObject(mCamera);
	mCamera->setFOVy(Degree(53));
	mCamera->setPosition(0, 7.5, -16);
	mCamera->setDirection(Vector3(0,-.3,1));

	chaseCam->target = car->getSceneNode();
	chaseCam->useSpring = true;

	hud = new HUD(mRoot);

	OgreApplication* app = OgreApplication::getSingletonPtr();
	app->setSceneManager(mSceneMgr);
	app->setDynWorld(phyWorld);
//	app->mHud = hud;

//    GnashManager::getSingletonPtr()->init();
//    gnashRoot = GnashManager::getSingletonPtr()->root;

//	CompositorInstance* bloom = Ogre::CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "Bloom");
//	Ogre::CompositorManager::getSingleton().setCompositorEnabled(mCamera->getViewport(), "Bloom", true);

//	luaL_dofile(app->L, "init.lua");

	mViewport->getTarget()->addListener(new BaseRTTListener(mSceneMgr, mViewport, new BaseMaterialSwitcher()));


	mExitGame = false;
}



void Level1::exit()
{
	mSceneMgr->clearScene();

//	delete mPlane;
//	delete mPlaneEnt;
//	delete mPlaneNode;

	//!! Note: This is supposed to be mSceneMgr->destroyAllCameras(); for CVS head
	mRoot->getAutoCreatedWindow()->removeAllViewports();
}

void Level1::pause()
{
}

void Level1::resume()
{
}

bool Level1::frameStarted(const FrameEvent& evt)
{
	car->UpdateComponents(evt.timeSinceLastFrame);
	
//	carLightNode->setPosition(car->mNode->getPosition());

//    hud->carSpeed = (car->getBody()->getLinearVelocity()*btVector3(1,0,1)).length();

//    SphereSceneQuery* ssq = mSceneMgr->createSphereQuery(Sphere(mCamera->getDerivedPosition(), 10.0));
//    RaySceneQueryResult* rayresult = ssq->execute();

//    sunBB->setPosition(sun->getPosition());


//    if(gnashRoot)
//    try
//    {
//    GnashManager::getSingletonPtr()->vclock->resume();
//    gnashRoot->advanceMovie();
//    gnashRoot->display();
//    GnashUtils::blit(GnashManager::getSingletonPtr()->offscreenbuf.get(), GnashManager::getSingletonPtr()->texture);
//    }
//    catch(...)
//    {
//        return false;
//    }


	return true;
}

bool Level1::frameEnded(const FrameEvent& evt)
{
	if (mExitGame)
		return false;

	phyWorld->stepSimulation(timeMulti*evt.timeSinceLastFrame, 5);
//	phyWorld->stepSimulation(timeMulti*evt.timeSinceLastFrame, 10, 1.f/90.f);
//    phyWorld->stepSimulation(timeMulti*evt.timeSinceLastFrame, 10);

	dbgdraw->step();

	const Real scale = 3.0f;
	hud->speed = car->vehicle->getCurrentSpeedKmHour()/scale;

	return true;
}

void Level1::keyPressed(const OIS::KeyEvent &e)
{
	if (!fixCamera)
		if (dynamic_cast<FlyCamera*>(cam) != NULL)
			dynamic_cast<FlyCamera*>(cam)->onKeyDown(e);

	switch (e.key) {
		case OIS::KC_F3:
			dbgdraw->setDebugMode(showDebug = !showDebug);
			break;

		case OIS::KC_1:
			cam = cameras[0];
			mCamera->getParentSceneNode()->detachObject(mCamera);
			cam->attachObject(mCamera);

			mCamera->setDirection(Vector3::UNIT_Z);
			mCamera->setPosition(0, 7, -21);
			mCamera->setDirection(Vector3(0,-.2,1));

			hud->print("Chase Camera");
			break;

		case OIS::KC_2:
			cam = cameras[1];
			mCamera->getParentSceneNode()->detachObject(mCamera);
			cam->attachObject(mCamera);
			fixCamera = false;

			hud->print("Free Fly Camera");
			break;

		case OIS::KC_3:
			cam = cameras[1];
			mCamera->getParentSceneNode()->detachObject(mCamera);
			cam->attachObject(mCamera);
			fixCamera = true;

			hud->print("Fixed Fly Camera");
			break;

		case OIS::KC_EQUALS:
			timeMulti *= 2;
			hud->print("Time Multiplier: " + StringConverter::toString(timeMulti));
			break;

		case OIS::KC_MINUS:
			timeMulti /= 2;
			hud->print("Time Multiplier: " + StringConverter::toString(timeMulti));
			break;

		case OIS::KC_T:
			mViewport->setMaterialScheme((useShaders = !useShaders)?"default":"NoShaders");
			break;

		case OIS::KC_R:
			mCamera->setPolygonMode((showWireframe=!showWireframe)?PM_WIREFRAME:PM_SOLID);
			break;

		case OIS::KC_NUMPAD1:
			if (dynamic_cast<ChaseCamera*>(cam) != NULL)
				dynamic_cast<ChaseCamera*>(cam)->useSpring = false;
			cam->translate(cam->getOrientation()*Vector3::UNIT_Z);
			break;

		case OIS::KC_NUMPAD2:
			if (dynamic_cast<ChaseCamera*>(cam) != NULL)
				dynamic_cast<ChaseCamera*>(cam)->useSpring = false;
			cam->rotate(Vector3::UNIT_X, Degree(1), Node::TS_LOCAL);
			break;

		case OIS::KC_NUMPAD4:
			if (dynamic_cast<ChaseCamera*>(cam) != NULL)
				dynamic_cast<ChaseCamera*>(cam)->useSpring = false;
			cam->rotate(Vector3::UNIT_Y, Degree(1), Node::TS_LOCAL);
			break;

		case OIS::KC_NUMPAD5:
			if (dynamic_cast<ChaseCamera*>(cam) != NULL)
				dynamic_cast<ChaseCamera*>(cam)->useSpring = true;
			break;

		case OIS::KC_NUMPAD6:
			if (dynamic_cast<ChaseCamera*>(cam) != NULL)
				dynamic_cast<ChaseCamera*>(cam)->useSpring = false;
			cam->rotate(Vector3::UNIT_Y, Degree(-1), Node::TS_LOCAL);
			break;

		case OIS::KC_NUMPAD8:
			if (dynamic_cast<ChaseCamera*>(cam) != NULL)
				dynamic_cast<ChaseCamera*>(cam)->useSpring = false;
			cam->rotate(Vector3::UNIT_X, Degree(-1), Node::TS_LOCAL);
			break;

		case OIS::KC_LEFT:
		case OIS::KC_A:
			car->steeringIncrement = 0.165f;
			break;

		case OIS::KC_RIGHT:
		case OIS::KC_D:
			car->steeringIncrement = -0.165f;
			break;

		case OIS::KC_UP:
		case OIS::KC_W:
			car->engineIncrement = 1.0f;
			break;

		case OIS::KC_DOWN:
		case OIS::KC_S:
			car->brakeIncrement = 1.0f;
			break;
		default:
			break;
		}
}

void Level1::keyReleased(const OIS::KeyEvent &e)
{

	if (!fixCamera)
		if (dynamic_cast<FlyCamera*>(cam) != NULL)
			dynamic_cast<FlyCamera*>(cam)->onKeyUp(e);

	switch (e.key) {
		case OIS::KC_F:
			break;

		case OIS::KC_UP:
		case OIS::KC_W:
			car->engineIncrement = .0f;
//            car->vehicle->mEngineForce = .0f;
			break;

		case OIS::KC_DOWN:
		case OIS::KC_S:
			car->brakes = .0f;
			car->brakeIncrement = .0f;
			break;

		case OIS::KC_LEFT:
		case OIS::KC_RIGHT:
		case OIS::KC_A:
		case OIS::KC_D:
			car->steeringIncrement = .0f;
			break;

		case OIS::KC_ESCAPE:
			mExitGame = true;
			break;
		default:
			break;
		}
}

void Level1::mouseMoved(const OIS::MouseEvent &e)
{

	if (dynamic_cast<FlyCamera*>(cam) != NULL) {
			const OIS::MouseState &ms = e.state;

			Degree mRotX = Degree(-ms.X.rel * 0.13);
			Degree mRotY = Degree(-ms.Y.rel * 0.13);

			mCamera->yaw(mRotX);
			mCamera->pitch(mRotY);
		}

//	if ( gnashRoot->notify_mouse_moved(e.state.X.abs, e.state.Y.abs) ) {
////        gnashRoot->display();
//	}

//    DisplayObject* dObj = gnashRoot->getDraggingCharacter();
//    if(!dObj) return;
//    as_object* o = dObj->object();
//    as_value v = Reflect::callMethod(o, "doAction", object(L, "onMouseMove"));
//    object g = globals(L);
//    g["this"] = dObj;
//    g["selectedNode"] = mCurrentObject;
//    luaL_dostring(L, v.to_string().c_str());
//    g["this"] = nil;
//    g["selectedNode"] = nil;

}

void Level1::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
{
//    if(!gnashRoot) return;

//    if(gnashRoot->notify_mouse_clicked(true, 1)) {
//        gnashRoot->display();
//        GnashUtils::blit(offscreenbuf.get(), gnashTex);
//    }

//    if(!gnashRoot->isMouseOverActiveEntity()) return;

//    DisplayObject* dObj = gnashRoot->getActiveEntityUnderPointer();
//    if(!dObj) return;

//    as_object* o = dObj->object();
//    if(!o) return;
//
//    as_value v = Reflect::callMethod(o, "doAction", object(L, "onPress"));
//
//    object g = globals(L);
//    g["this"] = dObj;
//
//    if(mCurrentObject)
//        g["selectedNode"] = mCurrentObject;
//
//    g["root"] = const_cast<Movie*>(&gnashRoot->getRootMovie());
//
//    luaL_dostring(L, v.to_string().c_str());
//
//    g["this"] = nil;
//    g["selectedNode"] = nil;

}

void Level1::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
{
//    if(!gnashRoot) return;

//    if(gnashRoot->notify_mouse_clicked(false, 1)) {
//        gnashRoot->display();
////        GnashUtils::blit(offscreenbuf.get(), gnashTex);
//    }
//
//    if(!gnashRoot->isMouseOverActiveEntity()) return;

//    DisplayObject* dObj = gnashRoot->getActiveEntityUnderPointer();
//    if(!dObj) return;
//
//    as_object* o = dObj->object();
//    if(!o) return;
//
//    as_value v = Reflect::callMethod(o, "doAction", object(L, "onRelease"));
//
//    object g = globals(L);
//    g["this"] = dObj;
////    g["selectedNode"] = mCurrentObject;
//    g["root"] = const_cast<Movie*>(&gnashRoot->getRootMovie());
//
//    luaL_dostring(L, v.to_string().c_str());
//
//    g["this"] = nil;
////    g["selectedNode"] = nil;
}


void Level1::initBullet()
{
	LogManager::getSingletonPtr()->logMessage("*** Initializing Bullet Physics ***");

	// Build the broadphase
	int maxProxies = 1024;
	btVector3 worldAabbMin(-10000,-10000,-10000);
	btVector3 worldAabbMax(10000,10000,10000);
	btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);

	// Set up the collision configuration and dispatcher
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
	btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

	// The actual physics solver
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

	// The physics world
	phyWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
	phyWorld->setGravity(btVector3(0,-9.8,0));

	// Debug drawing...
	dbgdraw = new BtOgre::DebugDrawer(mSceneMgr->getRootSceneNode(), phyWorld);
	phyWorld->setDebugDrawer(dbgdraw);
	dbgdraw->setDebugMode(showDebug);

	// Custom callback
//	gContactAddedCallback = customContactCallback;
}




void Level1::createScene(void)
{
//    LogManager::getSingletonPtr()->setLogDetail(LL_LOW);

	// Set shadows
//    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
//    mSceneMgr->setShadowColour(ColourValue::White*0.7);

//    mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_MODULATIVE);

//    mSceneMgr->setShadowTexturePixelFormat(Ogre::PF_FLOAT16_R);
//    mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
//    mSceneMgr->setShadowTextureSelfShadow(true);
//
//    mSceneMgr->setShadowTextureCasterMaterial("ShadowCaster");
//    mSceneMgr->setShadowTextureReceiverMaterial("ShadowReceiver");
//

	// Texture quality & filtering
//    MaterialManager::getSingletonPtr()->setDefaultAnisotropy(8);
//    MaterialManager::getSingletonPtr()->setDefaultTextureFiltering(Ogre::TFO_ANISOTROPIC);
//    TextureManager::getSingletonPtr()->setDefaultNumMipmaps(5);


	createPlane();

//    createMirror();

//    loadSceneXml("scene.xml");

//    Node* sun = mSceneMgr->getRootSceneNode()->getChild("Sun");
//    Vector3 sunPos = sun->getPosition();
//
//    LensFlare* lensflare = new LensFlare(sunPos, mCamera, mSceneMgr, 250);
//    mRoot->addFrameListener(lensflare);


//    /// Attach the mirror camera
//	mirrorCamera->setPosition(0,1.2,-5);
//	car->mNode->attachObject(mirrorCamera);


//    /// Assign camera target
//	if (dynamic_cast<ChaseCamera*>(mCameraNode) != NULL)
//		dynamic_cast<ChaseCamera*>(mCameraNode)->target = car->mNode;

	/*
	    /// Overlays
		hud = OverlayManager::getSingleton().getByName("HUD/SpeedGauge");
	    hud->show();

		speedValue = OverlayManager::getSingleton().getOverlayElement("SpeedValue");
		speedGauge = OverlayManager::getSingleton().getOverlayElement("SpeedGauge");

	    mHud = new HUD(mRoot);
	*/

	/// Compositors
//    Ogre::CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "Bloom");
//    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mCamera->getViewport(), "Bloom", true);


//
//
//    luaL_dostring(L,
//      "cam = app:getCamera()\n"
//      "root = app:getRootSceneNode()\n"
//      "sceneManager = app:getSceneManager()\n"
//      "hud = app:getHUD()\n"
//    );
//
//    luaL_dofile( L, "init.lua" );


}


void Level1::createPlane(void)
{
	/// Create a prefab plane
	mPlane = new MovablePlane("Plane1");
	mPlane->d = 0;
	mPlane->normal = Vector3::UNIT_Y;
	MeshPtr meshPtr = MeshManager::getSingleton().createPlane("Plane",
	                  ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
	                  *mPlane, 10000, 10000,
	                  200, 200, true, 1, 20, 20, Vector3::UNIT_Z);

	mPlaneEnt = mSceneMgr->createEntity("Plane", "Plane");
	meshPtr->buildTangentVectors();

	mPlaneEnt->setMaterialName("Suberban");

	mPlaneEnt->setCastShadows(false);
//    mPlaneEnt->setQueryFlags(WATER);
//    mPlaneEnt->setRenderQueueGroup(Ogre::RENDER_QUEUE_SKIES_LATE);
//    // Attach the rtt entity to the root of the scene
	mPlaneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	mPlaneNode->attachObject(mPlaneEnt);
	mPlaneNode->attachObject(mPlane);
	mPlaneNode->translate(0,-45.375,0);
}

void Level1::createMirror(void)
{
}
/*
void OgreApplication::createMirror(void) {
    Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual("RttTex",
          ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, mWindow->getWidth()/4, mWindow->getHeight()/4, 0, PF_R8G8B8,
          TU_RENDERTARGET);

    renderTexture = texture->getBuffer()->getRenderTarget();

    renderTexture->addViewport(mirrorCamera);
    renderTexture->getViewport(0)->setClearEveryFrame(true);
    renderTexture->getViewport(0)->setBackgroundColour(ColourValue::Black);
    renderTexture->getViewport(0)->setOverlaysEnabled(false);
    renderTexture->setAutoUpdated(true);

    Ogre::Rectangle2D *miniScreen = new Ogre::Rectangle2D(true);
    miniScreen->setCorners(-0.4, 0.95, 0.4, 0.5);
    miniScreen->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE));

    miniScreenNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode");
    miniScreenNode->attachObject(miniScreen);

    MaterialPtr material = MaterialManager::getSingleton().create("RttMat", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
    Ogre::Technique *technique = material->createTechnique();
    technique->createPass();
    material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
    material->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex");

    miniScreen->setMaterial("RttMat");

	}
*/

/**
* Create cameras
*/
void Level1::createCamera(void)
{
	// Create the camera
	mCamera = mSceneMgr->createCamera("Camera");
	mCamera->setDirection(Vector3::UNIT_Z);
	mCamera->setNearClipDistance(0.1);
	mCamera->setFarClipDistance(10000);

	mCamera->setPosition(0, 5, -20);

	// Camera nodes
	flyCam = new FlyCamera(mSceneMgr);
	chaseCam = new ChaseCamera(mSceneMgr);

	mRoot->addFrameListener(chaseCam);
	mRoot->addFrameListener(flyCam);

	// Attach Real Camera to Camera Node
	chaseCam->attachObject(mCamera);
//	mCameraNode = chaseCam;

//    flyCam->attachObject(mCamera);
//    mCameraNode = flyCam;

//	mirrorCamera = mSceneMgr->createCamera("MirrorCamera");
//	mirrorCamera->setDirection(Vector3::NEGATIVE_UNIT_Z);
//	mirrorCamera->setNearClipDistance(0.1);
//	mirrorCamera->setFarClipDistance(100);
}
